package br.sales.controller;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

import sun.misc.BASE64Encoder;
import br.sales.entity.DynamicQuery;
import br.sales.entity.UserEntity;
import br.sales.entity.exception.EntityExistsException;
import br.sales.entity.exception.EntityNotExistsException;
import br.sales.persistence.IPersistence;
import br.sales.persistence.PersistenceFactory;
import br.sales.persistence.exception.DBContainerNotInitializedException;

public class UserEntityControllerImpl implements IUserEntityController {

	private static IUserEntityController userEnittyController;
	
	
	public UserEntityControllerImpl() {
	}
	
	public static IUserEntityController getInstance(){
		if (userEnittyController == null){
			synchronized (IUserEntityController.class) {
				if (userEnittyController == null){
					userEnittyController = new UserEntityControllerImpl();
				}
			}
		}
		return userEnittyController;
	}
	
	@Override
	public UserEntity authenticate(String login, String password) throws DBContainerNotInitializedException {
		IPersistence persistence = PersistenceFactory.createSessionDB4ODAO();
		UserEntity u = null;
		u = new UserEntity(login,generatePassword(password));
		u = (UserEntity) persistence.retrieveByExample(u);
		return u;
	}

	@Override
	public String generatePassword(String pass) {
		MessageDigest digest;  
	    try {
			digest = MessageDigest.getInstance("SHA-512");
			digest.update(pass.getBytes());  
			BASE64Encoder encoder = new BASE64Encoder(); 
			return encoder.encode(digest.digest()).toString().trim();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}  
	    return "";
	}

	@Override
	public UserEntity createUserEntity(UserEntity userEntity)
			throws DBContainerNotInitializedException, EntityExistsException {
		
		IPersistence persistence = PersistenceFactory.createSessionDB4ODAO();
		try {
			UserEntity u =  null;
			u = retrieveUserEntity(userEntity.getLogin(),persistence);
			if (u == null){
				u =  createUserEntity(userEntity,persistence);
				u.setId(persistence.getObjectId(u));
				persistence.update(u);
				persistence.commit();
				return u;
			}
			else{
				throw new EntityExistsException();
			}
		}catch (DBContainerNotInitializedException e) {
			throw new DBContainerNotInitializedException();
		}
	}

	@Override
	public UserEntity createUserEntity(UserEntity userEntity,
			IPersistence persistence)
			throws DBContainerNotInitializedException, EntityExistsException {
		 userEntity.setPass(generatePassword(userEntity.getPass()));
		 userEntity = (UserEntity) persistence.save(userEntity);
		 return userEntity;
	}

	@Override
	public UserEntity retrieveUserEntity(String login)
			throws DBContainerNotInitializedException {
		UserEntity  u = new UserEntity(login);
		return retrieveUserEntity(u);
	}

	@Override
	public UserEntity retrieveUserEntity(UserEntity userEntity)
			throws DBContainerNotInitializedException {
		IPersistence persistence = PersistenceFactory.createSessionDB4ODAO();
		try {
		 return (UserEntity) persistence.retrieveByExample(userEntity);
		} catch (DBContainerNotInitializedException e) {
			throw new DBContainerNotInitializedException();
		}
	}

	@Override
	public UserEntity retrieveUserEntity(String login, IPersistence persistence)
			throws DBContainerNotInitializedException {
		UserEntity  u = new UserEntity(login);
		return retrieveUserEntity(u,persistence);
	}

	@Override
	public UserEntity retrieveUserEntity(UserEntity userEntity,
			IPersistence persistence) throws DBContainerNotInitializedException {
		return (UserEntity) persistence.retrieveByExample(userEntity);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<UserEntity> listAllUsers() throws DBContainerNotInitializedException {
		IPersistence persistence = PersistenceFactory.createSessionDB4ODAO();
		try {
			return  persistence.retrieveAll(UserEntity.class);
		}
		catch (DBContainerNotInitializedException e) {
			throw new DBContainerNotInitializedException();
		}
	}

	@Override
	public UserEntity updateUserEntity(UserEntity userEntity)
			throws Exception {
		IPersistence persistence = PersistenceFactory.createSessionDB4ODAO();
		UserEntity u =  null;
		try{
			u = retrieveUserEntity(userEntity.getLogin(),persistence);
			if (u != null){
				// u.copyFields(userEntity);
				u =  updateUserEntity(userEntity,persistence);
				persistence.commit();
				return u;
			}
			else{
				throw new EntityNotExistsException();
			}
		}	catch (DBContainerNotInitializedException e) {
			throw new DBContainerNotInitializedException();
		}
	}
	
	@Override
	public UserEntity updateUserEntity(UserEntity userEntity, IPersistence persistence)
			throws DBContainerNotInitializedException {
		 userEntity = (UserEntity) persistence.update(userEntity);
		 return userEntity;
	}

	
	@Override
	public void deleteUserEntity(UserEntity userEntity)
			throws DBContainerNotInitializedException,  EntityNotExistsException {
		IPersistence persistence = PersistenceFactory.createSessionDB4ODAO();
		UserEntity u =  null;
		try{
			u = retrieveUserEntity(userEntity.getLogin(),persistence);
			if (u != null){
				removeUserReferences(userEntity,persistence);
				deleteUserEntity(userEntity,persistence);
				persistence.commit();
			}
			else{
				throw new EntityNotExistsException();
			}
		}	catch (DBContainerNotInitializedException e) {
			throw new DBContainerNotInitializedException();
		}
	}
	
	@Override
	public void deleteUserEntity(UserEntity userEntity, IPersistence persistence)
			throws DBContainerNotInitializedException {
		persistence.delete(userEntity);
	}

	private void removeUserReferences(UserEntity userEntity, IPersistence persistence) {
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<UserEntity> listByValue(String value)
			throws DBContainerNotInitializedException {
		
		IPersistence persistence = PersistenceFactory.createSessionDB4ODAO();
		try{
				List<DynamicQuery> dqs = new ArrayList<DynamicQuery>();
				DynamicQuery dq1 = new DynamicQuery(DynamicQuery.LIKE, "login", value);
				DynamicQuery dq2 = new DynamicQuery(DynamicQuery.LIKE, DynamicQuery.OR, "email", value);
				dqs.add(dq1);dqs.add(dq2);
				return persistence.createNativeQuery(dqs, UserEntity.class);
			
		}catch (DBContainerNotInitializedException e) {
			throw new DBContainerNotInitializedException();
		}
	}
	
	
}
